package com.bonc.excel.sql;

import cn.hutool.core.date.DateUtil;
import com.mysql.cj.Messages;
import com.mysql.cj.MysqlConnection;
import com.mysql.cj.Query;
import com.mysql.cj.exceptions.ExceptionFactory;
import com.mysql.cj.interceptors.QueryInterceptor;
import com.mysql.cj.jdbc.ClientPreparedStatement;
import com.mysql.cj.jdbc.JdbcConnection;
import com.mysql.cj.jdbc.interceptors.ResultSetScannerInterceptor;
import com.mysql.cj.jdbc.result.ResultSetInternalMethods;
import com.mysql.cj.log.Log;
import com.mysql.cj.protocol.Resultset;
import com.mysql.cj.protocol.ServerSession;
import com.mysql.cj.util.Util;
import org.apache.poi.ss.formula.functions.T;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.function.Supplier;
import java.util.regex.Matcher;


/**
 * @Author: wujing
 * @Date: 2024/10/9 16:31
 * @Description: TODO
 **/

//@Component
public class Mysql8QueryInterceptor implements QueryInterceptor {
    private Map<String, String> preExecuteValues = new HashMap<>();

    private Map<String, String> postExecuteValues = new HashMap<>();

    private JdbcConnection connection;

    private Log log;

    @Override
    public QueryInterceptor init(MysqlConnection conn, Properties props, Log l) {
        this.connection = (JdbcConnection) conn;
        this.log = l;
        return this;
    }
    @Override
    public <T extends Resultset> T postProcess(Supplier<String> sql, Query interceptedQuery, T originalResultSet, ServerSession serverSession) {
        System.out.println("拦截器 postProcess");
        if(null == interceptedQuery){
            //项目启动中正在加载数据库 直接返回
            return null;
        }
        String currentDatabase = interceptedQuery.getCurrentDatabase();
        System.out.println("database:::"+currentDatabase);
        String sqlStr = sql.get();
        System.out.println(sqlStr);

        //解析sql获取库以及表名 select才走后续

        //加载脱敏表 以及 需要脱敏得字段
        //select * from cate_cnf_info
        // database:::dynamic_excel
        // categroy:::面向数据资产纳管与数据服务
        // name:::数据资产注册纳管情况
        // eval_req:::数据资产注册率100%
        // categroy:::面向数据生产
        // name:::数据生命周期纳管（分租户）
        // eval_req:::管理要求：各条线有效期占比不低于60%

        //if 配置了数据库以及表名才走对应脱敏逻辑
        return (T) Proxy.newProxyInstance(originalResultSet.getClass().getClassLoader(), new Class[]{ResultSetInternalMethods.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if ("equals".equals(method.getName())) {
                    return args[0].equals(this);
                } else {
                    Object invocationResult = method.invoke(originalResultSet, args);
                    String methodName = method.getName();
                    if (invocationResult != null && invocationResult instanceof String && "getString".equals(methodName)) {
                        return dealString(sqlStr, invocationResult, args);
                    }
                    return invocationResult;
                }
            }
        });
    }


    private void populateMapWithSessionStatusValues(Map<String, String> toPopulate) {
        try {
            try (Statement stmt = this.connection.createStatement()) {
                toPopulate.clear();

                try (ResultSet rs = stmt.executeQuery("SHOW SESSION STATUS")) {
                    while (rs.next()) {
                        toPopulate.put(rs.getString(1), rs.getString(2));
                    }
                }
            }
        } catch (SQLException ex) {
            throw ExceptionFactory.createException(ex.getMessage(), ex);
        }
    }

    @Override
    public <T extends Resultset> T preProcess(Supplier<String> sql, Query interceptedQuery) {
        System.out.println("拦截器1 preProcess");
        //System.out.println(DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"));
        return null; // we don't actually modify a result set
    }

    @Override
    public boolean executeTopLevelOnly() {
        return true;
    }

    @Override
    public void destroy() {
        this.connection = null;
        this.log = null;
    }



    public Object dealString(String sql, Object obj, Object... org) throws SQLException {
        if (obj == null || org == null || org.length == 0) {
            return obj;
        }


        //           在jpa中传过来的phone可能变成 phone5_0_，为了兼容jpa放弃精确匹配字段的方法
        //字段名字
        String key = String.valueOf(org[0]);
        //字段值
        String value = String.valueOf(obj);

        System.out.println(key+":::"+value);
        if (key.contains("phone")) {
            char[] chars = value.toCharArray();
            int length = chars.length / 3;
            for (int i = length; i < 2 * length; i++) {
                chars[i] = '*';
            }
            return new String(chars);
        } else if (key.contains("password")) {
            //return DesUtil.encrypt(value);
            return "pass";
        } else if (key.contains("categroy")) {
            //return DesUtil.encrypt(value);
            return "******";
        }
        else if (key.contains("id")) {
            //return DesUtil.encrypt(value);
            return "**";
        }
        return obj;
    }
}
